<template>
  <div class="common-table-container">
    <el-table
      :data="data"
      row-key="id"
      ref="tableRef"
      :height="tableHeight"
      @selection-change="handleSelectionChangeWithEmit"
      @cell-click="handleCellClickWithEmit"
      v-el-table-infinite-scroll="handleInfiniteScrollWithEmit"
      :row-class-name="getRowClassName"
      :default-expand-all="false"
      lazy
      v-loading="loading"
    >
      <!-- 动态渲染列 -->
      <el-table-column
        v-for="column in tableColumns"
        :key="column.prop || column.label"
        :prop="column.prop"
        :label="column.label"
        :width="column.width"
        :fixed="column.fixed"
        :type="column.type"
        :sortable="column.sortable"
        :align="column.align || 'left'"
        :formatter="column.formatter"
        :selectable="column.checkSelectable"
      >
        <!-- 自定义插槽内容 -->
        <template #default="scope" v-if="column.slot && column.slot !== 'actions'">
          <slot :name="column.slot" :row="scope.row" :column="scope.column" :$index="scope.$index">
            {{ scope.row[column.prop] }}
          </slot>
        </template>

        <!-- 多文字省略 -->
        <template #default="scope" v-if="column.slot && column.slot == 'ellipsis'">
          <div style="width: 100%">
            <el-popover
              effect="dark"
              placement="top"
              popper-style="text-align: center; width: auto; max-width: 400px;"
              :hide-after="100"
              :show-after="500"
              :content="scope.row[column.prop]"
            >
              <template #reference>
                <span class="text">{{ scope.row[column.prop] }}</span>
              </template>
            </el-popover>
          </div>
        </template>

        <!-- 图片预览 -->
        <template #default="scope" v-if="column.slot && column.slot == 'image'">
          <image-preview v-if="scope.row[column.prop]" :src="scope.row[column.prop]" :width="50" :height="50" />
        </template>

        <!-- Tag 标签 -->
        <template #default="scope" v-if="column.slot && column.slot == 'tag'">
          <el-tag type="success" v-if="typeof scope.row[column.prop] === 'string' && scope.row[column.prop]">
            {{ scope.row[column.prop] }}
          </el-tag>
          <template v-else-if="scope.row[column.prop]">
            <el-tag type="success" v-for="item in scope.row[column.prop]">
              <span class="tag-text">{{ item.name || item }}</span>
            </el-tag>
          </template>
        </template>

        <!-- 图标 -->
        <template #default="scope" v-if="column.slot && column.slot == 'icon'">
          <svg-icon :icon-class="scope.row[column.prop]" />
        </template>

        <!-- 按钮 -->
        <template #default="scope" v-if="column.slot && column.slot == 'button'">
          <el-button
            :type="column.buttonType || 'primary'"
            :size="column.buttonSize || 'default'"
            :link="column.link !== true"
            v-hasPermi="column.hasPermi"
            @click="column.onClick && column.onClick(scope.row)"
          >
            {{ column.buttonText }}
          </el-button>
        </template>

        <!-- input -->
        <template #default="scope" v-if="column.slot && column.slot == 'input'">
          <el-input
            v-model="scope.row[column.prop]"
            :disabled="column.disabled"
            :readonly="column.readonly"
            :clearable="column.clearable"
            @keyup.enter="column.handler && column.handler(scope.row)"
          />
        </template>

        <!-- 数字输入框 -->
        <template #default="scope" v-if="column.slot && column.slot == 'number'">
          <el-input-number
            v-show="shouldShowColumn(column, scope.row)"
            v-model="scope.row[column.prop]"
            :controls="false"
            @keyup.enter="column.handler && column.handler(scope.row)"
            @change="column.change && column.change(scope.row)"
            @blur="column.blur && column.blur(scope.row)"
          />
          <span v-show="showNumberText(column, scope.row)">{{ scope.row[column.prop] || '--' }}</span>
        </template>

        <!-- 选择器 -->
        <template #default="scope" v-if="column.slot && column.slot == 'select'">
          <el-select
            v-show="shouldShowColumn(column, scope.row)"
            v-model="scope.row[column.prop]"
            :placeholder="column.placeholder || `请选择${column.label}`"
            style="width: 100%"
            :multiple="column.multiple"
            :multiple-limit="column.multipleLimit || 0"
            :disabled="column.disabled"
            :clearable="column.clearable"
            :collapse-tags="column.collapseTags"
            :max-collapse-tags="column.maxCollapseTags"
            filterable
            @change="column.change && column.change(scope.row)"
          >
            <el-option
              v-for="option in getOptionsForItem(column)"
              :key="option.value"
              :label="option.label"
              :value="option.value"
            />
          </el-select>
        </template>

        <!-- tree选择器 -->
        <template #default="scope" v-if="column.slot && column.slot == 'tree-select'">
          <el-tree-select
            v-show="shouldShowColumn(column, scope.row)"
            v-model="scope.row[column.prop]"
            :placeholder="column.placeholder || `请选择${column.label}`"
            :multiple="column.multiple"
            :clearable="column.clearable"
            :render-after-expand="false"
            :collapse-tags="column.collapseTags"
            :data="getOptionsForItem(column)"
            :show-checkbox="column.showCheckbox"
            :max-collapse-tags="column.maxCollapseTags"
            :class="column.prop + '-tree-select'"
            @change="column.change && column.change($event, scope.row)"
            collapse-tags-tooltip
            filterable
            style="width: 100%"
          >
          </el-tree-select>
        </template>

        <!-- 操作列 -->
        <template #default="scope" v-if="column.slot === 'actions'">
          <div class="table-actions">
            <el-button
              v-for="action in getVisibleActions(scope.row)"
              v-hasPermi="action.hasPermi"
              :key="action.label"
              :type="action.type || 'primary'"
              :style="{ color: action.color }"
              :link="action.link !== false"
              :disabled="getActionDisabled(action, scope.row)"
              @click="handleActionClick(action, scope.row, $event)"
            >
              {{ action.label }}
            </el-button>
          </div>
        </template>
      </el-table-column>
      <!-- 处理没有数据的情况 -->
      <template #empty>
        <!-- <Empty />  自己的空状态组件-->
      </template>
    </el-table>
  </div>
</template>

<script setup lang="ts">
import { useElTable, type UseElTableOptions } from '@/hooks/useElTable';
type CommonTableProps = UseElTableOptions & {};
const props = defineProps<CommonTableProps>();

const tableRef = ref();

const {
  selectedRows, // 选中行
  loading, // 加载中
  tableColumns, // 表格列配置
  handleSelectionChange, // 处理选中行变化
  handleCellClick, // 处理单元格点击
  handleInfiniteScroll, // 处理无限滚动
  getVisibleActions, // 获取操作按钮
  handleActionClick, // 处理操作按钮点击
  clearSelection, // 清空选中行
  setLoading, // 设置加载中
  setInfiniteScroll, // 设置无限滚动
  getActionDisabled,
  tableHeight, // 表格高度
  infiniteScrollEnabled // 是否启用无限滚动
} = useElTable(props);

// 定义事件
const emit = defineEmits<{
  selectionChange: [selection: any[]];
  cellClick: [row: any, column: any, cell: any, event: Event];
  loadMore: [];
}>();

const shouldShowColumn = (column: any, row: any) => {
  return column.showColumn ? column.showColumn(row) : true;
};
const showNumberText = (column: any, row: any) => {
  return column.slot && column.slot === 'number' && column.columnType && column.columnType(row) == 'text';
};
// 获取选项数据的方法
const getOptionsForItem = (item: any) => {
  // 如果options是函数，则调用它获取最新数据
  if (typeof item.options === 'function') {
    return item.options();
  }

  // 如果options是数组，直接返回
  if (Array.isArray(item.options)) {
    return item.options;
  }

  // 如果options是ref或reactive对象，返回其值
  if (item.options && typeof item.options === 'object' && 'value' in item.options) {
    return item.options.value || [];
  }

  // 默认返回空数组
  return [];
};

// 重写处理函数以发出事件
const handleSelectionChangeWithEmit = (selection: any[]) => {
  const result = handleSelectionChange(selection);
  emit('selectionChange', result);
  return result;
};

const scrollToTop = async () => {
  await nextTick();
  // 确保 tableRef 已经被正确引用
  tableRef.value && tableRef.value.scrollTo({ top: 0 });
};

const handleCellClickWithEmit = (row: any, column: any, cell: any, event: Event) => {
  const result = handleCellClick(row, column, cell, event);
  emit('cellClick', result.row, result.column, result.cell, result.event);
  return result;
};

const getRowClassName = (row: any) => {
  return row.row.children && row.row.children.length > 0 ? 'has-children' : row.row.parentId ? '' : 'no-children';
};

const handleInfiniteScrollWithEmit = async () => {
  if (!infiniteScrollEnabled.value) return false;
  emit('loadMore');
  return handleInfiniteScroll();
};

// 清空选中行
const clearSelectedRows = async () => {
  await nextTick();
  clearSelection();
  tableRef.value && tableRef.value.clearSelection();
};

// 默认选中行
const setSelectedRows = async (row: any[]) => {
  tableRef.value!.toggleRowSelection(row, true);
};
// 暴露方法给父组件
defineExpose({
  selectedRows, // 选中行
  setSelectedRows, // 设置选中行
  clearSelection, // 清空选中行,
  clearSelectedRows, // 清空选中行 UI
  setLoading, // 设置加载中状态
  setInfiniteScroll, // 设置无限滚动状态
  scrollToTop // 滚动到顶部
});
</script>

<style scoped lang="scss">
.common-table-container {
  box-sizing: border-box;
  height: 100%;

  :deep(.el-input__wrapper),
  :deep(.el-select__wrapper) {
    min-height: 32px;
    border-radius: 12px;
  }

  /* 隐藏el-table的边框 */
  :deep(.el-table) {
    border: none !important;
    height: 100%;
  }

  /* 隐藏el-table-column的边框 */
  :deep(.el-table) th,
  :deep(.el-table) td,
  :deep(.el-table) thead {
    border: none !important;
    height: 40px;
    box-sizing: border-box;
    font-family:
      PingFang SC,
      PingFang SC;
    font-weight: 500;
    font-size: 12px !important;
  }

  :deep(.el-button + .el-button) {
    margin-left: 20px;
  }
  :deep(.el-button.is-disabled) {
    opacity: 0.5;
  }

  // 取消最后一行的边框
  :deep(.el-table__inner-wrapper:before) {
    width: 0 !important;
    color: #181d36;
  }

  /* 修改斑马纹偶数行的背景色 */
  :deep(.el-table .el-table__row:nth-child(odd)) {
    background-color: #ffffff;

    border-top-left-radius: 10px;
    border-bottom-left-radius: 10px;
  }

  /* 修改斑马纹奇数行的背景色 */
  :deep(.el-table .el-table__row:nth-child(even)) {
    background-color: #fafafa;
  }

  // 修改表头字体及背景色
  :deep(.el-table) th {
    background-color: #e5e8ef !important;
    font-family:
      PingFang SC,
      PingFang SC;
    font-weight: 500;
    font-size: 12px;
    color: #999999;
  }

  /* 设置第一列表头左上角圆角 */
  :deep(.el-table) th:first-child,
  :deep(.el-table) td:first-child {
    border-top-left-radius: 10px;
    border-bottom-left-radius: 10px;
  }

  /* 设置最后一列表头右上角圆角 */
  :deep(.el-table) th:last-child,
  :deep(.el-table) td:last-child {
    border-top-right-radius: 10px;
    border-bottom-right-radius: 10px;
  }

  // 文本溢出处理
  .table-cell-content {
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .table-actions {
    display: flex;
  }

  :deep(.el-table .no-children) {
    .cell {
      .el-table__placeholder {
        display: none;
      }
    }
  }
  // 单行文字省略

  .text {
    display: inline-block;
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  :deep(.el-table__row) {
    &.is-leaf {
      background-color: #f5f5f5;
      td:first-child {
        padding-left: 20px;
      }
    }
  }
  :deep(.el-table__body) {
    [class*='el-table__row--level-'] {
      td {
        &[class^='el-table_'][class*='_column_'] {
          .cell {
            width: 90%;
            display: flex;
            align-items: center;
            // justify-content: center;
            .el-table__placeholder {
              flex-shrink: 0;
            }
          }
        }
      }
    }
  }
}
.tag-text {
  display: inline-block;
  max-width: 100px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
</style>
